package com.winshare.saleAssistant.aspect;

import com.winshare.saleAssistant.domain.entity.StaffDO;
import com.winshare.saleAssistant.exception.BusinessException;
import com.winshare.saleAssistant.service.RedisService;
import com.winshare.saleAssistant.util.JacksonUtils;
import com.winshare.saleAssistant.util.RequestHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashSet;
import java.util.Set;


@Aspect
@Component
public class ControllerAspect {

    private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);

    private final static Set<String> noAuthUrlSet = new HashSet<>();

    private final HttpServletRequest request;

    private final RedisService redisService;


    public ControllerAspect(HttpServletRequest request, RedisService redisService) {
        this.request = request;
        this.redisService = redisService;
        noAuthUrlSet.add("/sys/login");
        noAuthUrlSet.add("/sys/getCaptchaImage");
        noAuthUrlSet.add("/sys/");
        noAuthUrlSet.add("/sys/login/phone");
        noAuthUrlSet.add("/sys/login/openId");
        noAuthUrlSet.add("/sys/loginOut");
        noAuthUrlSet.add("/sys/wx/get/openId");
        noAuthUrlSet.add("/sys/product/manage/preview");
        noAuthUrlSet.add("/sys/product/module/list");

        noAuthUrlSet.add("//sys/login");
        noAuthUrlSet.add("//sys/getCaptchaImage");
        noAuthUrlSet.add("//sys/");
        noAuthUrlSet.add("//sys/login/phone");
        noAuthUrlSet.add("//sys/login/openId");
        noAuthUrlSet.add("//sys/loginOut");
        noAuthUrlSet.add("//sys/wx/get/openId");
        noAuthUrlSet.add("//sys/product/manage/preview");
        noAuthUrlSet.add("//sys/product/module/list");
    }

    @Pointcut("execution(public * com.winshare.saleAssistant.controller.*.*(..))")
    public void aspect() {
    }

    @AfterReturning(value = "aspect()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        Signature signature = joinPoint.getSignature();
        logger.info("{}#{}方法出参：{}", signature.getDeclaringType().getSimpleName(), signature.getName(), JacksonUtils.writeValueAsString(result));
    }

    @Before("aspect()")
    public void doBefore(JoinPoint joinPoint) {
        logger.info("===========请求URL:{}", request.getRequestURI());
        if (noAuthUrlSet.contains(request.getRequestURI())) {
            return;
        }
        String token = request.getHeader("token");

        if (StringUtils.isEmpty(token)) {
            throw new BusinessException("登录凭证不能为空!");
        }
        StaffDO staffDO = redisService.getCurrentUserInfo(token);
        if (null == staffDO) {
            throw new BusinessException("登录时间已过期,请重新登录!");
        }
        String method = request.getHeader("user-agent");
        if (!StringUtils.isEmpty(method)) {
            if (method.contains("MicroMessenger")) {
                staffDO.setSourceType("mini");
            } else {
                staffDO.setSourceType("pc");
            }
        }
        redisService.tokenExpireTimeUpdate(token, 3600);
        RequestHolder.add(staffDO);

        Object[] args = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();
        if (args != null && args.length > 0) {
            // 系统日志
            String[] names = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < names.length; i++) {
                if (args[i] instanceof CharSequence) {
                    stringBuilder.append(String.format("%s: %s; ", names[i], args[i]));
                } else if (args[i] instanceof HttpServletRequest
                        || args[i] instanceof HttpServletResponse
                        || args[i] instanceof HttpSession
                        || args[i] instanceof MultipartFile
                        || args[i] instanceof MultipartFile[]) {
                    continue;
                } else {
                    stringBuilder.append(String.format("%s: %s; ", names[i], JacksonUtils.writeValueAsString(args[i])));
                }
            }
            logger.info("来源:{},{}#{}方法入参：{}", staffDO.getSourceType(), signature.getDeclaringType().getSimpleName(), signature.getName(), stringBuilder.toString());
        }
    }
}
